package com.linln.common.config;


import com.linln.common.utils.ReflectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.support.JpaEntityInformation;
import org.springframework.data.jpa.repository.support.SimpleJpaRepository;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import java.util.List;
import java.util.Optional;

/**
 * 专门处理修改时，只修改非null的属性到数据库中
 *
 * @param <T>
 * @param <ID>
 * @author taofucheng
 */
public class SimpleJpaRepositoryImpl<T, ID> extends SimpleJpaRepository<T, ID> implements BaseRepository<T, ID> {

    private final JpaEntityInformation<T, ?> entityInformation;
    private final EntityManager em;

    @Autowired
    public SimpleJpaRepositoryImpl(JpaEntityInformation<T, ?> entityInformation, EntityManager entityManager) {
        super(entityInformation, entityManager);
        this.entityInformation = entityInformation;
        this.em = entityManager;
    }

    /**
     * 通用save方法 ：新增/选择性更新
     */
    @SuppressWarnings("unchecked")
    @Override
    @Transactional(rollbackFor = Exception.class)
    public <S extends T> S save(S entity) {
        // 获取ID
        ID entityId = (ID) entityInformation.getId(entity);
        Optional<T> optionalT;
        if (entityId == null) {
            // 标记为新增数据
            optionalT = Optional.empty();
        } else {
            // 若ID非空 则查询最新数据
            optionalT = findById(entityId);
        }
        // 若根据ID查询结果为空
        if (!optionalT.isPresent()) {
            em.persist(entity);// 新增
            return entity;
        } else {
            // 1.获取最新对象
            T target = optionalT.get();
            // 2.将非空属性覆盖到最新对象
            ReflectUtils.copyNotNullProperties(entity, target);
            // 3.更新非空属性
            em.merge(target);
            return entity;
        }
    }

    /**
     * 完整保存
     *
     * @param entity
     * @return
     */
    @Override
    public <S extends T> S saveFully(S entity) {
        if (entityInformation.isNew(entity)) {
            em.persist(entity);
            return entity;
        } else {
            return em.merge(entity);
        }
    }

    /**
     * 批量更新数据状态
     * #{#entityName} 实体类对象
     *
     * @param status 状态
     * @param id     ID列表
     * @return 更新数量
     */
    @Override
    public Integer updateStatus(Byte status, List<ID> id) {
        return null;//这个方法其实是没有用的，因为接口上定义了Query语句。
    }
}
